////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//	MathFrustrum.cpp
//  MathLib
//
//  Created by Gregory Maks on 8/14/09.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "Math.h"



void Frustrum::ctor()
{
	leftPlane.ctor();
	rightPlane.ctor();
	topPlane.ctor();
	bottomPlane.ctor();
	nearPlane.ctor();
	farPlane.ctor();
}

Frustrum::Frustrum()
{
	ctor();
}

Frustrum::Frustrum(const Frustrum &aFrustrum)
{
	leftPlane	= aFrustrum.leftPlane;
	rightPlane	= aFrustrum.rightPlane;
	topPlane	= aFrustrum.topPlane;
	bottomPlane	= aFrustrum.bottomPlane;
	nearPlane	= aFrustrum.nearPlane;
	farPlane	= aFrustrum.farPlane;
}

Frustrum::Frustrum(Matrix4x4 &aMatrix, bool bNormalizePlanes)
{
	ctor();
	ExtractPlanesFromViewProjectionMatrix(aMatrix, bNormalizePlanes);
}

void Frustrum::ExtractPlanesFromViewProjectionMatrix (Matrix4x4 &matrix, bool bNormalizePlanes)
{
	leftPlane.normal.x = matrix.n[0][3] + matrix.n[0][0];
	leftPlane.normal.y = matrix.n[1][3] + matrix.n[1][0];
	leftPlane.normal.z = matrix.n[2][3] + matrix.n[2][0];
	leftPlane.distance = matrix.n[3][3] + matrix.n[3][0];
	
	rightPlane.normal.x = matrix.n[0][3] - matrix.n[0][0];
	rightPlane.normal.y = matrix.n[1][3] - matrix.n[1][0];
	rightPlane.normal.z = matrix.n[2][3] - matrix.n[2][0];
	rightPlane.distance = matrix.n[3][3] - matrix.n[3][0];
	
	topPlane.normal.x = matrix.n[0][3] - matrix.n[0][1];
	topPlane.normal.y = matrix.n[1][3] - matrix.n[1][1];
	topPlane.normal.z = matrix.n[2][3] - matrix.n[2][1];
	topPlane.distance = matrix.n[3][3] - matrix.n[3][1];
	
	bottomPlane.normal.x = matrix.n[0][3] + matrix.n[0][1];
	bottomPlane.normal.y = matrix.n[1][3] + matrix.n[1][1];
	bottomPlane.normal.z = matrix.n[2][3] + matrix.n[2][1];
	bottomPlane.distance = matrix.n[3][3] + matrix.n[3][1];
	
	nearPlane.normal.x = matrix.n[0][2];
	nearPlane.normal.y = matrix.n[1][2];
	nearPlane.normal.z = matrix.n[2][2];
	nearPlane.distance = matrix.n[3][2];
	
	farPlane.normal.x = matrix.n[0][3] - matrix.n[0][2];
	farPlane.normal.y = matrix.n[1][3] - matrix.n[1][2];
	farPlane.normal.z = matrix.n[2][3] - matrix.n[2][2];
	farPlane.distance = matrix.n[3][3] - matrix.n[3][2];
	
	//normalizing planes
	if (bNormalizePlanes)
	{
		leftPlane.Normalize();
		rightPlane.Normalize();
		topPlane.Normalize();
		bottomPlane.Normalize();
		nearPlane.Normalize();
		farPlane.Normalize();
	}
}

bool Frustrum::TestRect(Rect3D &aRect)
{
	if (nearPlane.GetRectVsPlaneClassification(aRect) == PlaneClassification_Back) return false;
	if (farPlane.GetRectVsPlaneClassification(aRect) == PlaneClassification_Back) return false;
	if (bottomPlane.GetRectVsPlaneClassification(aRect) == PlaneClassification_Back) return false;
	if (topPlane.GetRectVsPlaneClassification(aRect) == PlaneClassification_Back) return false;
	if (rightPlane.GetRectVsPlaneClassification(aRect) == PlaneClassification_Back) return false;
	if (leftPlane.GetRectVsPlaneClassification(aRect) == PlaneClassification_Back) return false;
	
	return true;
}

bool Frustrum::TestQuad(QuadPoly3D &aQuad)
{
	if (nearPlane.GetQuadVsPlaneClassification(aQuad) == PlaneClassification_Back) return false;
	if (farPlane.GetQuadVsPlaneClassification(aQuad) == PlaneClassification_Back) return false;
	if (bottomPlane.GetQuadVsPlaneClassification(aQuad) == PlaneClassification_Back) return false;
	if (topPlane.GetQuadVsPlaneClassification(aQuad) == PlaneClassification_Back) return false;
	if (rightPlane.GetQuadVsPlaneClassification(aQuad) == PlaneClassification_Back) return false;
	if (leftPlane.GetQuadVsPlaneClassification(aQuad) == PlaneClassification_Back) return false;
	
	return true;
}
























